4  常用内置函数

4.1 引言Python内置函数的价值

Python提供了丰富的内置函数,这些函数无需导入任何模块即可直接使用。在金融数据分析中,熟练掌握这些内置函数可以显著提高代码的简洁性和执行效率。

理论背景:Batteries Included哲学

Python的设计哲学之一是”Batteries Included”(自带电池),这意味着标准库提供了丰富的功能,使得开发者可以快速完成常见任务,而无需重复造轮子。内置函数是这一哲学的极致体现。

4.2 序列处理函数

4.2.1 len()获取序列长度

len()函数返回对象(字符串、列表、元组、字典等)的长度或项目个数。

时间复杂度: - 列表、元组、字符串: O(1) - 字典、集合: O(1)

列表 4.1
# ==================== 创建数据 ====================
# 示例数据:2018年净利润排名前10位的证券公司列表
# stock是一个列表,包含10个证券公司名称字符串
# 方括号[]用于创建列表,元素用逗号分隔
stock = ["中信证券", "国泰君安", "海通证券", "华泰证券", "广发证券",  # 前5家公司
         "招商证券", "申万宏源", "国信证券", "中信建投", "中国银河"]  # 后5家公司

# ==================== 获取列表长度 ====================
# len()函数返回列表的元素个数
# num_companies变量存储公司总数
num_companies = len(stock)  # 计算列表长度,结果是10
# f-string格式化输出,{num_companies}会被替换为变量值
print(f"证券公司数量: {num_companies}")  # 输出: 证券公司数量: 10

# ==================== 应用场景:检查数据完整性 ====================
# expected_count定义期望的公司数量
expected_count = 10  # 期望有10家公司
# if语句进行条件判断,len(stock)获取实际数量
# ==是比较运算符,判断两边是否相等
if len(stock) == expected_count:  # 如果实际数量等于期望数量
    print("数据完整")  # 输出提示信息
else:  # 如果不相等
    # f-string中可以插入多个变量
    print(f"数据缺失,期望{expected_count}家,实际{len(stock)}家")  # 输出缺失信息

4.2.2 enumerate()枚举索引和值

enumerate()函数在遍历序列时同时返回索引和值,这在生成带序号的报告时非常有用。

语法: enumerate(iterable, start=0)

列表 4.2
# ==================== 生成带排名的公司列表 ====================
# enumerate()函数同时返回索引和值
# stock是前面的证券公司列表
# start=1表示索引从1开始(更符合人类习惯的排名,默认从0开始)
ranked_companies = list(enumerate(stock, start=1))  # 创建(排名,公司名)元组的列表

# ==================== 输出排名信息 ====================
# 输出标题
print("2018年净利润排名前10位的证券公司:")  # 打印标题
# for循环遍历ranked_companies列表
# rank接收排名(索引),company接收公司名(值)
for rank, company in ranked_companies:  # 解包元组,遍历每个元素
    # f-string格式化输出
    # {rank:2d}表示rank占2位,不足2位右对齐
    # {company}显示公司名
    print(f"  {rank:2d}. {company}")  # 输出格式化的排名和公司名

# ==================== 输出示例 ====================
# 输出:
# 2018年净利润排名前10位的证券公司:
#    1. 中信证券
#    2. 国泰君安
#    ...

金融应用场景: - 生成排名报告 - 带时间戳的时间序列数据处理 - 多重列表的嵌套循环

4.2.3 sum()求和计算

sum()函数对可迭代对象进行求和,支持初始值参数。

语法: sum(iterable, start=0)

列表 4.3
# ⚠️ 平台原始代码 - 请原样输入至教学平台(注释除外),平台才会判定答案正确
stock = ["中信证券","国泰君安","海通证券","华泰证券","广发证券","招商证券","申万宏源","国信证券","中信建设","中国银河"]  # 定义列表stock
# 定义列表profit
profit = [98.7643,70.7004,57.7071,51.6089,46.3205,44.4626,42.4781,34.3125,31.0343,29.3174]
# 定义列表return_Q1
return_Q1 = [0.547783,0.315274,0.594318,0.383333,0.275237,0.307463,0.356265,0.617682,1.93341,0.734604]
price = [24.78,20.15,14.03,22.41,16.17,17.52,5.52,13.54,25.55,11.83]  # 定义列表price
#输出列表中元素的个数
print(len(stock))   

#以列表方式输出stock
print(list(enumerate(stock,start=1)))  

#计算10家证券公司的净利润总和
profit_total =sum(profit)       

#计算每家证券公司平均净利润
profit_average =profit_total/len(stock)    

print("2018年净利润排名前10位的证券公司净利润总和(亿元)",profit_total)  # 输出2018年净利润排名前10位的证券公司净利润总和(
print("2018年净利润排名前10位的证券公司净利润平均数(亿元)",round(profit_average,4))  # 输出2018年净利润排名前10位的证券公司净利润平均数
#找出最大涨幅
return_max =max(return_Q1)    
#找出最小涨幅
return_min =min(return_Q1)                       

print("2019年1季度股价的最大涨幅",return_max)  # 输出2019年1季度股价的最大涨幅
print("2019年1季度股价的最小涨幅",return_min)  # 输出2019年1季度股价的最小涨幅
#将股价由小到大排序
price_sorted =sorted(price)                  
print(price_sorted)  # 输出按价格升序排列的证券公司股价列表

性能提示: 对于大型数值数组,numpy.sum()比内置sum()快得多,应优先使用。

4.3 极值函数

4.3.1 max()求最大值

max()函数返回可迭代对象的最大值或多个参数中的最大值。

列表 4.4
# ==================== 创建数据 ====================
# 示例数据:2019年1季度股价涨跌幅
# return_Q1列表存储10只股票的季度收益率
# 数据以小数形式表示(例如0.547783表示54.7783%)
return_Q1 = [0.547783, 0.315274, 0.594318, 0.383333, 0.275237,  # 前5只收益率
             0.307463, 0.356265, 0.617682, 1.93341, 0.734604]  # 后5只收益率

# ==================== 找出最大涨幅 ====================
# max()函数找出列表中的最大值
# return_max存储最大的收益率值
return_max = max(return_Q1)  # 找出最大收益率
# f-string格式化输出
# :.2%表示格式化为百分数,保留2位小数
print(f"2019年1季度股价的最大涨幅: {return_max:.2%}")  # 输出最大涨幅

# ==================== 应用场景:识别表现最佳股票 ====================
# .index()方法返回元素在列表中第一次出现的索引位置
# return_max是最大收益率值
# best_index存储最大收益率对应的索引
best_index = return_Q1.index(return_max)  # 获取最大值的索引位置
# stock[best_index]通过索引获取对应的证券公司名称
best_company = stock[best_index]  # 获取表现最佳的公司名
# 输出公司名和对应的涨幅
print(f"表现最佳: {best_company}, 涨幅: {return_max:.2%}")  # 输出最佳表现股票

# ==================== 输出示例 ====================
# 输出: 表现最佳: 中信建投, 涨幅: 193.34%

4.3.2 min()求最小值

min()函数返回可迭代对象的最小值或多个参数中的最小值。

列表 4.5
# ==================== 找出最小涨幅 ====================
# min()函数找出列表中的最小值
# return_min存储最小的收益率值
return_min = min(return_Q1)  # 找出最小收益率
# f-string格式化输出,:.2%表示百分数格式
print(f"2019年1季度股价的最小涨幅: {return_min:.2%}")  # 输出最小涨幅

# ==================== 应用场景:识别风险资产 ====================
# if语句判断最小涨幅是否为负数(即下跌)
# <是比较运算符,判断左边是否小于右边
if return_min < 0:  # 如果最小涨幅为负(下跌)
    # .index()方法获取最小值的索引位置
    worst_index = return_Q1.index(return_min)  # 获取最小值索引
    # 通过索引获取对应的公司名
    worst_company = stock[worst_index]  # 获取表现最差的公司名
    # 输出警告信息,包括公司名和跌幅
    print(f"注意: {worst_company}跌幅为{return_min:.2%}")  # 输出风险提示

补充说明:key参数

max()min()函数支持key参数,可以自定义比较标准:

列表 4.6
# ==================== 创建复杂数据 ====================
# stocks_info是一个列表,包含多个字典
# 每个字典存储一只股票的信息(名称、净利润、市盈率)
stocks_info = [  # 列表,包含3个字典元素
    {'name': '中信证券', 'profit': 98.76, 'pe': 15.2},  # 字典1:键值对存储股票信息
    {'name': '国泰君安', 'profit': 70.70, 'pe': 12.8},  # 字典2
    {'name': '海通证券', 'profit': 57.71, 'pe': 18.5}   # 字典3
]

# ==================== 按净利润找出最大 ====================
# max()函数的key参数指定比较标准
# lambda x: x['profit']定义匿名函数
# x是stocks_info中的每个元素(字典)
# x['profit']提取字典中'profit'键对应的值
# max会根据这个值进行比较,返回整个字典元素
most_profitable = max(stocks_info, key=lambda x: x['profit'])  # 按利润找最大
# ['name']提取字典中name键的值
print(f"最盈利: {most_profitable['name']}")  # 输出最盈利的公司

# ==================== 按PE比率找出最小(最便宜) ====================
# min()函数找出PE最小的股票(估值最低)
# lambda x: x['pe']定义提取pe值的函数
# PE越低通常表示股票越便宜
cheapest = min(stocks_info, key=lambda x: x['pe'])  # 按PE找最小
print(f"最低PE: {cheapest['name']}")  # 输出PE最低的公司

4.4 排序函数

4.4.1 sorted()排序操作

sorted()函数返回排序后的新列表,原对象保持不变。

语法: sorted(iterable, key=None, reverse=False)

列表 4.7
# ==================== 创建数据 ====================
# 示例数据:10只股票的股价(单位:元)
# price列表存储每只股票的价格
price = [24.78, 20.15, 14.03, 22.41, 16.17, 17.52, 5.52, 13.54, 25.55, 11.83]

# ==================== 升序排序 ====================
# sorted()函数返回排序后的新列表
# 默认reverse=False,升序排列(从小到大)
# 原列表price保持不变
price_sorted = sorted(price)  # 按升序排序
print("股价排序(升序):")  # 输出标题
print(price_sorted)  # 输出排序后的列表

# ==================== 降序排序 ====================
# reverse=True参数指定降序排列(从大到小)
# 这在金融分析中常用于找出最高价
price_desc = sorted(price, reverse=True)  # 按降序排序
print("\n股价排序(降序):")  # 输出标题,\n表示换行
print(price_desc)  # 输出降序排列的列表

# ==================== 金融应用:识别高估和低估股票 ====================
# 假设公允价值为18元,作为估值基准
fair_value = 18.0  # 设定公允价值

# 列表推导式筛选高估股票(价格>公允价值)
# p for p in price遍历每个价格
# if p > fair_value是筛选条件
# overvalued列表存储所有高估股票的价格
overvalued = [p for p in price if p > fair_value]  # 筛选高估股票

# 列表推导式筛选低估股票(价格<公允价值)
# undervalued列表存储所有低估股票的价格
undervalued = [p for p in price if p < fair_value]  # 筛选低估股票

# ==================== 输出统计结果 ====================
# len()函数计算列表长度,得到股票数量
print(f"\n高估股票数量: {len(overvalued)}")  # 输出高估股票数量
print(f"低估股票数量: {len(undervalued)}")  # 输出低估股票数量

sorted() vs .sort():

特性 sorted() .sort()
返回值 新列表 None(原地修改)
原对象 不变 改变
适用对象 所有可迭代对象 仅列表
链式操作 支持 不支持
列表 4.8
# ==================== sorted():创建新列表 ====================
# prices列表包含3个价格
prices = [24.78, 20.15, 14.03]  # 创建价格列表
# sorted()返回新的排序后列表,原列表不变
sorted_prices = sorted(prices)  # 升序排序,返回新列表
print(f"原列表: {prices}")  # 输出原列表(未改变)
print(f"新列表: {sorted_prices}")  # 输出排序后的新列表

# ==================== .sort():原地修改 ====================
# .copy()方法创建列表的副本,避免修改原列表
prices_copy = prices.copy()  # 复制列表
# .sort()方法直接在原列表上排序,返回None
prices_copy.sort()  # 原地排序,修改列表本身
print(f"修改后: {prices_copy}")  # 输出排序后的列表(已改变)

# ==================== 应用场景选择 ====================
# - 需要保留原数据:使用sorted()
# - 内存敏感:使用.sort()

4.5 类型转换函数

4.5.1 int(), float(), str()类型转换

这些函数在不同数据类型之间进行转换。

列表 4.9
# ==================== 场景1:从CSV读取的数据转换 ====================
# CSV文件读取的数据通常是字符串类型
# price_str是字符串形式的股价
price_str = "1850.50"  # 字符串类型的价格
# volume_str是字符串形式的成交量
volume_str = "2500000"  # 字符串类型的成交量

# ==================== 转换为数值类型 ====================
# float()函数将字符串转换为浮点数
# price现在是数值类型,可以进行数学运算
price = float(price_str)  # 将"1850.50"转换为1850.5

# int()函数将字符串转换为整数
# volume现在是整数类型
volume = int(volume_str)  # 将"2500000"转换为2500000

# ==================== 计算成交额 ====================
# *运算符执行乘法
# price * volume计算成交额(价格×成交量)
turnover = price * volume  # 计算成交额
# f-string格式化输出,:,表示千位分隔符
# :,.0f表示带千位分隔符的浮点数,0位小数
print(f"成交额: {turnover:,.0f}元")  # 输出: 4,626,250,000元

# ==================== 场景2:格式化输出 ====================
# amount是浮点数,表示金额
amount = 1234567.89  # 浮点数金额
# str()函数将数值转换为字符串
# amount_str现在是字符串类型
amount_str = str(amount)  # 转换为字符串"1234567.89"
# 字符串可以用于文本拼接
print(f"成交金额: {amount_str}元")  # 输出字符串

# ==================== 场景3:处理缺失值 ====================
# missing_values列表包含各种可能的缺失值表示
# 空字符串""、"N/A"、"None"、"1850.50"(有效值)
missing_values = ["", "N/A", "None", "1850.50"]  # 包含缺失值的列表

# ==================== 遍历并处理缺失值 ====================
# for循环遍历列表中的每个值
for val in missing_values:  # 遍历每个元素
    # if语句检查是否为缺失值
    # not in检查val是否不在缺失值列表中
    if val not in ["", "N/A", "None"]:  # 如果不是缺失值
        # 转换为浮点数
        price = float(val)  # 转换有效值为浮点数
        # 输出有效价格
        print(f"有效价格: {price}")  # 输出: 有效价格: 1850.5
    else:  # 如果是缺失值
        # 输出缺失值标识
        print(f"缺失值: {val}")  # 输出缺失值类型

4.6 四舍五入函数

4.6.1 round()数值舍入

round()函数对数值进行四舍五入。

语法: round(number, ndigits=None)

重要说明: Python 3采用”银行家舍入”(Round Half to Even)策略: - 2.5 → 2 (最近的偶数) - 3.5 → 4 (最近的偶数)

这在金融计算中可能导致意外结果。

列表 4.10
# ==================== 计算平均净利润 ====================
# profit_total是前面计算的净利润总和
# len(stock)获取公司数量
# /计算平均值
profit_average = profit_total / len(stock)  # 计算平均净利润

# ==================== 不同精度的舍入 ====================
# 输出精确值(无舍入)
print(f"精确值: {profit_average}")  # 输出完整精度的平均值

# round(profit_average, 4)保留4位小数
print(f"保留4位小数: {round(profit_average, 4)}")  # 保留4位小数

# round(profit_average, 2)保留2位小数
print(f"保留2位小数: {round(profit_average, 2)}")  # 保留2位小数

# round(profit_average)不指定ndigits,取整
print(f"取整: {round(profit_average)}")  # 取整

# ==================== 银行家舍入示例 ====================
# 输出标题
print("\n银行家舍入示例:")  # \n换行

# round(2.5)按照银行家舍入规则
# 2和3都是2.5等距离的整数,选择偶数2
print(f"round(2.5) = {round(2.5)}")  # 输出: 2

# round(3.5)按照银行家舍入规则
# 3和4都是3.5等距离的整数,选择偶数4
print(f"round(3.5) = {round(3.5)}")  # 输出: 4

# ==================== 金融应用:建议使用Decimal模块 ====================
# Decimal模块提供精确的十进制运算
# ROUND_HALF_UP指定四舍五入(而非银行家舍入)
from decimal import Decimal, ROUND_HALF_UP  # 导入Decimal和舍入模式

# Decimal('2.5')创建Decimal对象
# quantize()方法按指定格式舍入
# Decimal('1')表示整数格式
# rounding=ROUND_HALF_UP指定常规四舍五入
value = Decimal('2.5')  # 创建Decimal对象
rounded = value.quantize(Decimal('1'), rounding=ROUND_HALF_UP)  # 常规舍入
print(f"常规舍入: {rounded}")  # 输出: 3

4.7 统计函数

Python 3.4+在statistics模块中提供了丰富的统计函数:

列表 4.11
# ==================== 导入统计模块 ====================
# statistics是Python标准库的统计模块
import statistics  # 导入statistics模块

# ==================== 创建示例数据 ====================
# returns列表包含8个收益率数据
# 既有正收益也有负收益
returns = [0.05, 0.03, -0.02, 0.04, 0.06, 0.02, -0.01, 0.07]

# ==================== 基本统计量计算 ====================
# statistics.mean()计算算术平均值
mean = statistics.mean(returns)  # 计算平均收益率

# statistics.median()计算中位数
median = statistics.median(returns)  # 计算中位数

# statistics.stdev()计算样本标准差
# 样本标准差使用n-1作为分母
stdev = statistics.stdev(returns)  # 计算样本标准差

# statistics.variance()计算样本方差
# 方差是标准差的平方
variance = statistics.variance(returns)  # 计算样本方差

# ==================== 输出统计结果 ====================
# f-string格式化输出,:.4f保留4位小数
print(f"算术平均: {mean:.4f}")  # 输出平均值
print(f"中位数: {median:.4f}")  # 输出中位数
print(f"标准差: {stdev:.4f}")  # 输出标准差
print(f"方差: {variance:.4f}")  # 输出方差

# ==================== 金融应用:风险收益分析 ====================
# 定义无风险利率(通常参考国债利率)
risk_free_rate = 0.02  # 无风险利率2%

# 计算超额收益(平均收益减去无风险利率)
excess_return = mean - risk_free_rate  # 计算超额收益率

# 计算夏普比率(风险调整后收益指标)
# 夏普比率 = 超额收益 / 标准差
# 衡量每承担一单位风险获得的超额收益
sharpe_ratio = excess_return / stdev  # 计算夏普比率

# 输出风险调整后收益指标
# :.4f保留4位小数
print(f"\n夏普比率: {sharpe_ratio:.4f}")  # 输出夏普比率

4.8 函数式编程工具

4.8.1 map()映射函数

map()函数将指定函数应用于可迭代对象的每个元素。

语法: map(function, iterable, ...)

列表 4.12
# ==================== 示例1:类型转换 ====================
# price_strings列表包含字符串形式的股价
# 数据可能来自CSV或文本文件
price_strings = ["24.78", "20.15", "14.03", "22.41", "16.17"]

# ==================== 使用map进行类型转换 ====================
# map(function, iterable)将函数应用于每个元素
# float是内置函数,将字符串转换为浮点数
# price_strings是可迭代对象
# map返回迭代器,需要用list()转换为列表
price_floats = list(map(float, price_strings))  # 批量转换为浮点数
# 输出转换结果
print(f"转换结果: {price_floats}")  # 输出浮点数列表

# ==================== 示例2:计算涨跌幅 ====================
# prices_old是调整前的价格列表
prices_old = [100, 105, 98, 102, 110]  # 旧价格

# prices_new是调整后的价格列表
prices_new = [105, 110, 95, 108, 115]  # 新价格

# ==================== 定义涨跌幅计算函数 ====================
# lambda定义匿名函数
# old, new是两个参数,代表旧价格和新价格
# (new - old) / old计算涨跌幅公式
calc_return = lambda old, new: (new - old) / old  # 定义收益率计算函数

# ==================== 使用map批量计算 ====================
# map可以接受多个可迭代对象
# calc_return应用于prices_old和prices_new对应位置的元素
# 例如: calc_return(100, 105), calc_return(105, 110), ...
returns = list(map(calc_return, prices_old, prices_new))  # 批量计算收益率

# 列表推导式格式化输出
# [f'{r:.2%}' for r in returns]将每个收益率格式化为百分数字符串
print(f"涨跌幅: {[f'{r:.2%}' for r in returns]}")  # 输出百分数形式的涨跌幅

4.8.2 filter()过滤函数

filter()函数根据指定函数的条件筛选元素。

语法: filter(function, iterable)

列表 4.13
# ==================== 示例1:筛选正收益股票 ====================
# all_returns列表包含多个收益率(正负都有)
all_returns = [0.05, -0.02, 0.03, -0.01, 0.04, -0.03, 0.06]

# ==================== 使用filter筛选正收益 ====================
# filter(function, iterable)根据函数条件筛选
# lambda x: x > 0定义筛选条件:收益率大于0
# filter返回迭代器,包含所有满足条件的元素
positive_returns = list(filter(lambda x: x > 0, all_returns))  # 筛选正收益

# 列表推导式格式化为百分数
# [f'{r:.2%}' for r in positive_returns]格式化每个正收益
print(f"正收益: {[f'{r:.2%}' for r in positive_returns]}")  # 输出正收益列表

# ==================== 示例2:筛选高收益股票 ====================
# lambda x: x > 0.03定义条件:收益率大于3%
# 这用于找出表现优异的股票
high_returns = list(filter(lambda x: x > 0.03, all_returns))  # 筛选高收益(>3%)
print(f"高收益: {[f'{r:.2%}' for r in high_returns]}")  # 输出高收益列表

# ==================== 应用场景:多条件筛选 ====================
# stocks列表包含多个字典,每个字典存储一只股票的信息
# 包括名称(name)、收益率(return)、风险(risk)
stocks = [
    {'name': 'A', 'return': 0.05, 'risk': 0.10},  # 股票A:收益5%,风险10%
    {'name': 'B', 'return': 0.08, 'risk': 0.15},  # 股票B:收益8%,风险15%
    {'name': 'C', 'return': 0.06, 'risk': 0.08}   # 股票C:收益6%,风险8%
]

# ==================== 筛选符合多条件的股票 ====================
# 筛选条件:收益>5% 且 风险<10%
# lambda s: s['return'] > 0.05 and s['risk'] < 0.10定义筛选函数
# s是每个股票字典
# s['return']和s['risk']访问对应键的值
# and逻辑运算符表示两个条件都要满足
filtered = list(filter(  # 筛选符合条件的股票
    lambda s: s['return'] > 0.05 and s['risk'] < 0.10,  # 多条件筛选函数
    stocks  # 待筛选的股票列表
))
# 列表推导式提取符合条件的股票名称
print(f"符合条件的股票: {[s['name'] for s in filtered]}")  # 输出: ['C']

4.8.3 zip()配对函数

zip()函数将多个可迭代对象的元素配对成元组。

列表 4.14
# ==================== 创建示例数据 ====================
# names列表存储证券公司名称
names = ["中信证券", "国泰君安", "海通证券"]

# prices列表存储对应的股价
prices = [24.78, 20.15, 14.03]

# volumes列表存储对应的成交量
volumes = [2500000, 1800000, 3200000]  # 成交量单位:股

# ==================== 使用zip组合多个列表 ====================
# zip()将多个列表的对应元素配对成元组
# 例如: ("中信证券", 24.78, 2500000), ("国泰君安", 20.15, 1800000), ...
# list()将zip对象转换为列表
stock_data = list(zip(names, prices, volumes))  # 组合三个列表

# ==================== 输出股票数据 ====================
print("股票数据:")  # 输出标题
# for循环遍历stock_data列表
# name, price, volume解包每个元组
for name, price, volume in stock_data:  # 遍历每只股票的数据
    # 计算成交额(价格×成交量)
    turnover = price * volume  # 计算成交额
    # f-string格式化输出
    # :.2f保留2位小数
    # :,添加千位分隔符
    print(f"  {name}: 价格={price:.2f}, 成交量={volume:,}, 成交额={turnover:,.0f}")

# ==================== 应用场景1:创建字典 ====================
# zip可以用来创建字典
# dict(zip(keys, values))将两个列表转换为字典
# names作为键,prices作为值
stock_dict = dict(zip(names, prices))  # 创建股票价格字典
# 输出字典
print(f"\n价格字典: {stock_dict}")  # 输出: {'中信证券': 24.78, ...}

# ==================== 应用场景2:同时遍历多个列表 ====================
print("\n按成交量排序:")  # 输出标题
# sorted()对zip对象排序
# key=lambda x: x[2]指定按成交量(第3个元素)排序
# x[2]表示元组的第3个元素(成交量)
for name, price, volume in sorted(zip(names, prices, volumes), key=lambda x: x[2]):
    # f-string格式化输出,:,添加千位分隔符
    print(f"  {name}: {volume:,}")  # 输出排序后的股票

4.9 综合应用实例

4.9.1 案例证券公司综合分析

列表 4.15
# ==================== 数据准备 ====================
# companies列表存储公司名称
companies = ["中信证券", "国泰君安", "海通证券", "华泰证券", "广发证券"]

# profits列表存储净利润(亿元)
profits = [98.76, 70.70, 57.71, 51.61, 46.32]  # 净利润数据

# prices列表存储股价(元)
prices = [24.78, 20.15, 14.03, 22.41, 16.17]  # 股价数据

# ==================== 1. 基本统计 ====================
# sum()计算净利润总和
total_profit = sum(profits)  # 净利润总额

# 计算平均净利润
avg_profit = total_profit / len(companies)  # 平均净利润

# max()找出最高净利润
max_profit = max(profits)  # 最高净利润

# min()找出最低净利润
min_profit = min(profits)  # 最低净利润

# ==================== 输出基本统计 ====================
# "=" * 50生成50个等号的分隔线
print("=" * 50)  # 输出分隔线
print("2018年净利润排名前5位证券公司分析")  # 输出标题
print("=" * 50)  # 输出分隔线

# 输出基本统计信息
print(f"\n【基本统计】")  # 输出小节标题
print(f"  净利润总额: {total_profit:.2f}亿元")  # 输出总额
print(f"  平均净利润: {avg_profit:.2f}亿元")  # 输出平均值
print(f"  最高净利润: {max_profit:.2f}亿元")  # 输出最大值
print(f"  最低净利润: {min_profit:.2f}亿元")  # 输出最小值

# ==================== 2. 排名分析 ====================
# zip()将公司名和利润配对
# sorted()按利润排序
# key=lambda x: x[1]指定按利润(元组第2个元素)排序
# reverse=True表示降序(从大到小)
sorted_profits = sorted(zip(companies, profits), key=lambda x: x[1], reverse=True)

# 输出净利润排名
print(f"\n【净利润排名】")  # 输出小节标题
# enumerate()添加排名序号,start=1从1开始
for rank, (company, profit) in enumerate(sorted_profits, 1):  # 遍历排序后的数据
    # f-string格式化输出
    # {rank}是排名,{company}是公司名,{profit:.2f}是利润(保留2位小数)
    print(f"  {rank}. {company}: {profit:.2f}亿元")  # 输出每条记录

# ==================== 3. 股价分析 ====================
# sorted()对股价排序
# key=lambda x: x[1]指定按股价(元组第2个元素)排序
# 默认升序(从低到高)
sorted_prices = sorted(zip(companies, prices), key=lambda x: x[1])

# 输出股价排名
print(f"\n【股价排名(从低到高)】")  # 输出小节标题
# enumerate()添加排名序号
for rank, (company, price) in enumerate(sorted_prices, 1):  # 遍历排序后的数据
    # 输出每条记录
    print(f"  {rank}. {company}: {price:.2f}元")  # 输出公司名和股价

# ==================== 4. 综合评价(高利润低股价) ====================
# 计算净利润股价比(类似市盈率的倒数)
# p / pr计算每元股价对应的净利润
# for p, pr in zip(profits, prices)同时遍历两个列表
# 结果是新的列表,存储每只股票的利润股价比
profit_price_ratios = [p / pr for p, pr in zip(profits, prices)]  # 计算比率

# zip()将公司名和比率配对
ratios = list(zip(companies, profit_price_ratios))  # 创建元组列表

# max()找出比率最高的(最被低估)
# key=lambda x: x[1]指定按比率比较
best_ratio = max(ratios, key=lambda x: x[1])  # 找出最高比率

# 输出投资价值分析
print(f"\n【投资价值分析】")  # 输出小节标题
# best_ratio[0]是公司名,best_ratio[1]是比率
# :.2f保留2位小数
print(f"  净利润/股价比最高: {best_ratio[0]} ({best_ratio[1]:.2f})")  # 输出最优选择